import fingerprint from '@fingerprintjs/fingerprintjs';
import { pick } from 'lodash';
import md5 from 'md5';

const getWebgpuFingerprint = async () => {
  const startTimer = Date.now()
  const defaultResult = {
    value: '',
    duration: Date.now() - startTimer
  }
  if (!navigator.gpu) {
    return defaultResult
  }

  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) {
    console.log('当前浏览器不支持WebGPU');
    return defaultResult;
  }

  const device = await adapter.requestDevice();

  // 请求设备支持的扩展
  const extensions = Array.from(adapter.features.values());

  // 获取硬件限制信息并手动序列化
  const limits = {};
  for (const key in device.limits) {
    limits[key] = device.limits[key];
  }

  // 序列化和哈希处理
  const serializedData = JSON.stringify({
    extensions,
    limits
  });

  return { value: serializedData, duration: Date.now() - startTimer }
};

const getWebGLFingerprint = async () => {
  const startTimer = Date.now();
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl');

  if (!gl) {
    return {
      value: '',
      duration: startTimer - Date.now()
    };
  }
  // 设置清除颜色为黑色，不透明
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // 清除颜色缓冲区
  gl.clear(gl.COLOR_BUFFER_BIT);

  // 创建顶点着色器
  const vsSource = `
                        attribute vec4 aVertexPosition;
                        void main(void) {
                                gl_Position = aVertexPosition;
                        }
        `;
  const vertexShader: any = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertexShader, vsSource);
  gl.compileShader(vertexShader);

  // 创建片段着色器
  const fsSource = `
                        void main(void) {
                                        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
                        }
        `;
  const fragmentShader: any = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, fsSource);
  gl.compileShader(fragmentShader);

  // 创建着色器程序
  const shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);

  // 定义三角形的顶点
  const vertices = new Float32Array([ 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0 ]);

  // 创建顶点缓冲区对象
  const vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  // 将缓冲区对象绑定到着色器变量
  const vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
  gl.enableVertexAttribArray(vertexPositionAttribute);
  gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

  // 绘制三角形
  gl.drawArrays(gl.TRIANGLES, 0, 3);

  // 读取渲染结果并生成指纹，sha256进行加密
  const result = canvas.toDataURL();
  return {
    value: result,
    duration: Date.now() - startTimer
  };
};

export const generateFingerprint = async () => {
  const fp = await fingerprint.load();
  const result = await fp.get();

  const predefinedComponents = pick(result.components, [
    'architecture',
    'audio',
    'canvas',
    'cpuClass',
    'deviceMemory',
    'hardwareConcurrency',
    'hdr',
    'osCpu',
    'platform',
    'vendor',
    'vendorFlavors',
    'videoCard'
  ]);

  const components = {
    ...predefinedComponents,
    webgl: await getWebGLFingerprint()
    // webgpu: await getWebgpuFingerprint()
  };

  if ('value' in components.canvas) {
    components.canvas.value.text = '';
  }

  const visitorId = fingerprint.hashComponents(components);

  return md5(visitorId + navigator.userAgent);
};